﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace Beeflys.Generator
{
    public sealed class Reflect
    {
        public static Reflect Create(CSharpCompilation compilation)
        {
            Reflect reflect = new Reflect();
            reflect.Parse(compilation);

            return reflect;
        }

        
        private Mapper mapper = new Mapper();
        private IAssemblySymbol assembly;
        private List<string> imports = new List<string>();

        public Mapper Mapper
        {
            get { return this.mapper; }
        }

        public IAssemblySymbol Assembly
        {
            get { return this.assembly; }
        }
        
        private Reflect Parse(CSharpCompilation compilation)
        {
            this.assembly = compilation.Assembly;
            var trees = compilation.SyntaxTrees;
            foreach (SyntaxTree tree in trees)
            {
                SemanticModel model = compilation.GetSemanticModel(tree);
                CompilationUnitSyntax root = (CompilationUnitSyntax)tree.GetRoot();
                
                this.SyntaxParse(model, root);
            }

            return new Reflect();
        }

        private void SyntaxParse(SemanticModel model, CompilationUnitSyntax root)
        {
            this.imports = root.GetImports();
            
            this.UsingParse(model, root.Usings);
            this.MembersParse(model, root.Members);
        }

        private void UsingParse(SemanticModel model, SyntaxList<UsingDirectiveSyntax> usings)
        {
            foreach (UsingDirectiveSyntax usingItem in usings)
            {
                var usingNameInfo = model.GetSymbolInfo(usingItem.Name);
                if (usingNameInfo.Symbol == null) continue;
                this.NamespaceParse((INamespaceSymbol) usingNameInfo.Symbol);
            }
        }


        private void MembersParse(SemanticModel model, SyntaxList<MemberDeclarationSyntax> members)
        {
            foreach (var member in members)
            {
                if (member is NamespaceDeclarationSyntax namespaceDeclarationSyntax)
                {
                    var symbolInfo = model.GetSymbolInfo(namespaceDeclarationSyntax.Name);
                    if (symbolInfo.Symbol == null) continue;
                    var symbol = symbolInfo.Symbol;
                    if (symbol is INamespaceSymbol namespaceSymbol)
                    {
                        this.NamespaceParse(namespaceSymbol);
                    }
                    else if(symbol is INamedTypeSymbol typeSymbol)
                    {
                        this.TypeParse(typeSymbol);
                    }
                    else
                    {
                        Console.WriteLine(symbol.GetType().FullName);
                    }
                }
                //直接解析class
                // else if(member is TypeDeclarationSyntax typeDeclarationSyntax)
                // {
                //     ClassDeclarationSyntax syntax = (ClassDeclarationSyntax) typeDeclarationSyntax;
                //     var symbolInfo = model.GetSymbolInfo(syntax);
                //     if (symbolInfo.Symbol == null) continue;
                //     //
                //     Console.WriteLine(symbolInfo.Symbol.Name);
                //
                //
                //     // this.TypeParse(typeSymbol);
                // }
            }
        }

        private void NamespaceParse(INamespaceSymbol namespaceSymbol)
        {
            var namespaceMembers = namespaceSymbol.GetNamespaceMembers();
            foreach (var member in namespaceMembers)
            {
                //嵌套命名空间
                this.NamespaceParse(member);
            }
            
            var typeMembers = namespaceSymbol.GetTypeMembers().ToList();
            this.TypesParse(typeMembers);
        }

        private void TypesParse(List<INamedTypeSymbol> typeSymbols)
        {
            foreach (var typeMember in typeSymbols)
            {
                string fullName = typeMember.ToString();
                if (mapper.Contains(fullName))
                {
                    continue;
                }

                this.TypeParse(typeMember);
            }
        }

        private void TypeParse(INamedTypeSymbol typeSymbol)
        {
            var fullName = typeSymbol.ToString();
            if (fullName.Contains(".<")) return;
            if (this.mapper.Contains(fullName)) return;
            
            // Console.WriteLine(typeSymbol.ToString() + "           " + typeSymbol.IsReferenceType + "          " +
            //                   typeSymbol.BaseType?.ToString());

            var item = UTypeHelper.Create(typeSymbol, this.imports, this);
            if (item == null) return;
            
            this.mapper.Add(item);

            //可能会有嵌套类
            List<INamedTypeSymbol> list = new List<INamedTypeSymbol>();
            var members = typeSymbol.GetMembers();
            foreach (var member in members)
            {
                if (member is INamedTypeSymbol symbol)
                {
                    list.Add(symbol);
                }
            }
            this.TypesParse(list);
        }
        
    }
}